home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / PCTAGS15.ARJ / TAGIO.C < prev    next >
C/C++ Source or Header  |  1991-10-05  |  13KB  |  363 lines

  1. /*
  2.  EPSHeader
  3.  
  4.    File: tagio.c
  5.    Author: J. Kercheval
  6.    Created: Wed, 07/17/1991  21:48:14
  7. */
  8. /*
  9.  EPSRevision History
  10.  
  11.    J. Kercheval  Sun, 08/18/1991  20:49:44  add fill_buffer()
  12.    J. Kercheval  Tue, 09/03/1991  23:25:13  add buffer_offset to fill_buffer()
  13.    J. Kercheval  Thu, 09/05/1991  20:13:01  add MergeFile()
  14.    J. Kercheval  Tue, 09/10/1991  23:55:47  add calls to external_cleanup() when exiting
  15.    J. Kercheval  Tue, 09/17/1991  19:41:16  add support for case_sensitive flag
  16. */
  17.  
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <io.h>
  22.  
  23. #include "tagio.h"
  24. #include "log.h"
  25.  
  26.  
  27. /* external_cleanup() is used on exit(1) for internal error */
  28. extern void external_cleanup(void);
  29.  
  30.  
  31. /*----------------------------------------------------------------------------
  32.  *
  33.  * FillBuffer() fills the passed buffer parameter with bufsize characters
  34.  * (or as many as are available) and places and null character '\0' at the
  35.  * end of the buffer.  This routine returns TRUE if successful and FALSE if
  36.  * eof(infile) is true.  Note: if a bufsize parameter is passed and the read
  37.  * is successful for bufsize characters, then buffer[bufsize] will be
  38.  * overwritten with the null character.  Do not pass a bufsize the maximum
  39.  * size of the buffer.  This null terminated buffering scheme assumes the
  40.  * source file has no null character embedded within it.
  41.  *
  42.  ---------------------------------------------------------------------------*/
  43.  
  44. BOOLEAN FillBuffer(FILE * infile, char *buffer, long int bufsize)
  45. {
  46.     long int size;
  47.  
  48.     /* init buffer */
  49.     *buffer = '\0';
  50.  
  51.     /* return if end of file */
  52.     if (feof(infile))
  53.         return FALSE;
  54.  
  55.     /* read the buffer from the file */
  56.     size = (long int) fread((void *) buffer, (size_t) sizeof(unsigned char),
  57.                             (size_t) bufsize, infile);
  58.  
  59.     /* place the end of buffer mark and return success */
  60.     buffer[size] = '\0';
  61.     return TRUE;
  62. }
  63.  
  64.  
  65. /*----------------------------------------------------------------------------
  66.  *
  67.  * GetLine will read a line not to exceed n-1 chars from f and will return
  68.  * true if any characters parsed
  69.  *
  70.  ---------------------------------------------------------------------------*/
  71.  
  72. BOOLEAN GetLine(FILE * f, char *line, int n)
  73. {
  74.     int i;                      /* looping variable (size of line) */
  75.     char c;                     /* temporary character variable */
  76.  
  77.     /* check for end of file */
  78.     if (feof(f))
  79.         return FALSE;
  80.  
  81.     for (i = 0, c = '\0'; !feof(f) && c != '\n' && i < n - 1; i++) {
  82.  
  83.         /* get next char */
  84.         c = (char) fgetc(f);
  85.  
  86.         /* check for end of line due to n-1th character read */
  87.         if (i == n - 2) {
  88.             log_message("# getline() -- long line encountered - truncating");
  89.             do {
  90.                 c = (char) fgetc(f);
  91.             } while (!feof(f) && c != '\n');
  92.         }
  93.  
  94.         /* write the character to the line */
  95.         line[i] = c;
  96.     }
  97.  
  98.     /* zero length string and end of file return FALSE */
  99.     if (feof(f) && i == 1)
  100.         return FALSE;
  101.  
  102.     /* write end of line and return */
  103.     line[i - 1] = '\0';
  104.     return TRUE;
  105. }
  106.  
  107.  
  108. /*----------------------------------------------------------------------------
  109.  *
  110.  * OutputTag() places the tag in the correct format into the output stream
  111.  *
  112.  ---------------------------------------------------------------------------*/
  113.  
  114. void OutputTag(FILE * outfile, char *line, char *symbol, char *infname,
  115.                 long int line_number, long int char_number, Flags * flags)
  116. {
  117.     /* epsilon style output */
  118.     if (flags->oe) {
  119.         fprintf(outfile, "%s;%s;%ld\n", symbol, infname, char_number);
  120.         return;
  121.     }
  122.  
  123.     /* GNU style output */
  124.     if (flags->og) {
  125.         fprintf(outfile, "%s\t%s\t/^%s$/\n", symbol, infname, line);
  126.         return;
  127.     }
  128.  
  129.     /* spaces delimited output */
  130.     if (flags->os) {
  131.         fprintf(outfile, "%s %s %ld\n", symbol, infname, line_number);
  132.         return;
  133.     }
  134.  
  135.     /* MicroSoft Error format */
  136.     if (flags->om) {
  137.         fprintf(outfile, "%s %s(%ld)\n", symbol, infname, line_number);
  138.         return;
  139.     }
  140.  
  141.     /* not reached */
  142.     log_message("# OutputTag -- internal error - continuing");
  143.     return;
  144. }
  145.  
  146.  
  147. /*----------------------------------------------------------------------------
  148.  *
  149.  * MergeFile() will take the temporary file and merge it into the potentially
  150.  * existing tag file.  During the merge, any tags from the input files which
  151.  * were processed during this session will be deleted from the tag file to
  152.  * prevent innaccurate tagging information.
  153.  *
  154.  ---------------------------------------------------------------------------*/
  155.  
  156. #define MAX_TAGFILE_LINE_LENGTH 4096
  157. #define MAXPATH 80
  158.  
  159. void MergeFile(char *input_filename, char *output_filename,
  160.                 ArgList arglist, Flags * flags)
  161. {
  162.     FILE *input_stream;         /* file pointer used for input */
  163.     FILE *new_tag_stream;       /* file pointer used by new tag stream */
  164.     FILE *output_stream;        /* file pointer used for output */
  165.  
  166.     char line1[MAX_TAGFILE_LINE_LENGTH];        /* line for new tag file */
  167.     char line2[MAX_TAGFILE_LINE_LENGTH];        /* line for old tag file */
  168.     char tag_filename[MAXPATH]; /* intermediate used to purge old tags */
  169.  
  170.     char delim[] = " \t;(";     /* list of valid delimiters for tag format */
  171.  
  172.     char *tmp_filename;         /* intermediate file name */
  173.  
  174.     char *token_start;          /* pointer to interesting tokens on purge */
  175.     int token_length;           /* length of token at token_start */
  176.  
  177.     int compare;                /* the results of a stricmp() */
  178.  
  179.     BOOLEAN file1ret;           /* true while new tag file in not at EOF */
  180.     BOOLEAN file2ret;           /* true while old tag file in not at EOF */
  181.  
  182.     if (access(output_filename, 00)) {
  183.  
  184.         /* open the new tags file for read */
  185.         if ((new_tag_stream = fopen(input_filename, "r")) ==
  186.             (FILE *) NULL) {
  187.             log_message("# MergeFile() -- error opening input file");
  188.             external_cleanup();
  189.             exit(1);
  190.         }
  191.  
  192.         /* open the tag output file for write */
  193.         if ((output_stream = fopen(output_filename, "w")) ==
  194.             (FILE *) NULL) {
  195.             log_message("# MergeFile() -- error opening tag file");
  196.             external_cleanup();
  197.             exit(1);
  198.         }
  199.  
  200.         /* the old tag output file doesn't exist yet, just copy it over */
  201.         while (GetLine(new_tag_stream, line1, MAX_TAGFILE_LINE_LENGTH)) {
  202.             fprintf(output_stream, "%s\n", line1);
  203.         }
  204.  
  205.         /* close the files */
  206.         fclose(new_tag_stream);
  207.         fclose(output_stream);
  208.     }
  209.     else {
  210.  
  211.         /* create the required temporary file name */
  212.         tmp_filename = tempnam(".\\", "tg");
  213.  
  214.         /* open the old tag file */
  215.         if ((input_stream = fopen(output_filename, "r")) ==
  216.             (FILE *) NULL) {
  217.             log_message("# MergeFile() -- error opening output file");
  218.             external_cleanup();
  219.             exit(1);
  220.         }
  221.  
  222.         /* open the temporary file */
  223.         if ((output_stream = fopen(tmp_filename, "w")) ==
  224.             (FILE *) NULL) {
  225.             log_message("# MergeFile() -- error opening temporary file");
  226.             external_cleanup();
  227.             exit(1);
  228.         }
  229.  
  230.         /* copy the output file to a temporary file and at the same time
  231.          * remove the old tags */
  232.         while (GetLine(input_stream, line1, MAX_TAGFILE_LINE_LENGTH)) {
  233.  
  234.             /* only output the line if the line is non zero in length */
  235.             if (line1[0] != '\0') {
  236.  
  237.                 /* pass the first token on the line */
  238.                 token_start = strpbrk(line1, delim);
  239.                 while (strspn(token_start, delim)) {
  240.                     token_start++;
  241.                 }
  242.  
  243.                 /* get the length of the second token on the line */
  244.                 token_length = strcspn(token_start, delim);
  245.  
  246.                 /* copy the name to a temporary variable */
  247.                 strncpy(tag_filename, token_start, token_length);
  248.                 tag_filename[token_length] = '\0';
  249.  
  250.                 /* if the token is not in argInput then output it */
  251.                 if (!ArgIsMember(arglist, tag_filename)) {
  252.                     fprintf(output_stream, "%s\n", line1);
  253.                 }
  254.             }
  255.         }
  256.  
  257.         /* close the open files */
  258.         fclose(input_stream);
  259.         fclose(output_stream);
  260.  
  261.         /* remove the old tag file */
  262.         remove(output_filename);
  263.  
  264.         /* open the temporary file for read */
  265.         if ((input_stream = fopen(tmp_filename, "r")) ==
  266.             (FILE *) NULL) {
  267.             log_message("# MergeFile() -- error opening input file");
  268.             external_cleanup();
  269.             exit(1);
  270.         }
  271.  
  272.         /* open the new tags file for read */
  273.         if ((new_tag_stream = fopen(input_filename, "r")) ==
  274.             (FILE *) NULL) {
  275.             log_message("# MergeFile() -- error opening input file");
  276.             external_cleanup();
  277.             exit(1);
  278.         }
  279.  
  280.         /* open the tag output file for write */
  281.         if ((output_stream = fopen(output_filename, "w")) ==
  282.             (FILE *) NULL) {
  283.             log_message("# MergeFile() -- error opening tag file");
  284.             external_cleanup();
  285.             exit(1);
  286.         }
  287.  
  288.         /* merge the new tags in with the old tags */
  289.         file1ret = GetLine(new_tag_stream, line1, MAX_TAGFILE_LINE_LENGTH);
  290.         file2ret = GetLine(input_stream, line2, MAX_TAGFILE_LINE_LENGTH);
  291.         while (file1ret || file2ret) {
  292.  
  293.             /* compare the lines and output in ascending order.  If the
  294.              * command line specified no sorting then place the new tags
  295.              * first and then the old tags.  This will result in slightly
  296.              * better performance for non-sorted tag finding algorithms
  297.              * assuming the last files tagged are the most likely to be used
  298.              * in the future */
  299.             if (file1ret && file2ret) {
  300.                 if (flags->sort_tags) {
  301.  
  302.                     /* determine the sort order */
  303.                     if (flags->case_sensitive)
  304.                         compare = strcmp(line1, line2);
  305.                     else
  306.                         compare = stricmp(line1, line2);
  307.  
  308.                     /* if the new tag is less than or equal to the old tag
  309.                      * then output the new tag */
  310.                     if (compare <= 0) {
  311.  
  312.                         /* output the new tag and get another line */
  313.                         fprintf(output_stream, "%s\n", line1);
  314.                         file1ret = GetLine(new_tag_stream, line1,
  315.                                            MAX_TAGFILE_LINE_LENGTH);
  316.                     }
  317.                     else {
  318.  
  319.                         /* output the old tag and get another line */
  320.                         fprintf(output_stream, "%s\n", line2);
  321.                         file2ret = GetLine(input_stream, line2,
  322.                                            MAX_TAGFILE_LINE_LENGTH);
  323.                     }
  324.                 }
  325.                 else {
  326.  
  327.                     /* just output from the new tag file and get another line */
  328.                     fprintf(output_stream, "%s\n", line1);
  329.                     file1ret = GetLine(new_tag_stream, line1,
  330.                                        MAX_TAGFILE_LINE_LENGTH);
  331.                 }
  332.             }
  333.             else {
  334.                 if (file2ret) {
  335.  
  336.                     /* new tag file is empty, just output line2, and get the
  337.                      * next line in old tag file */
  338.                     fprintf(output_stream, "%s\n", line2);
  339.                     file2ret = GetLine(input_stream, line2,
  340.                                        MAX_TAGFILE_LINE_LENGTH);
  341.                 }
  342.                 else {
  343.  
  344.                     /* old tag file is empty, just output line1, and get the
  345.                      * next line in new tag file */
  346.                     fprintf(output_stream, "%s\n", line1);
  347.                     file1ret = GetLine(new_tag_stream, line1,
  348.                                        MAX_TAGFILE_LINE_LENGTH);
  349.                 }
  350.             }
  351.         }
  352.  
  353.         /* close the open files */
  354.         fclose(input_stream);
  355.         fclose(new_tag_stream);
  356.         fclose(output_stream);
  357.  
  358.         /* remove the temporary file and free tmp_filename memory */
  359.         remove(tmp_filename);
  360.         free(tmp_filename);
  361.     }
  362. }
  363.